#include "./heat_task.h"
#include "../driver/sensor.h"
#include "../driver/parts.h"
#include "../utils/progress.h"
#include "../driver/analog.h"
#include "../service/config.h"

namespace task {

using namespace driver;
using namespace utils;
using namespace service;

void HeatTask::run() {

    for (;;) {
        switch (m_state) {
            case State::IDLE: do_idle(); break;
            case State::WORK: do_work(); break;
            case State::TEMP_FAIL: do_fail(); break;
            case State::STOP: do_fail(); break;
            case State::TIMEOUT: do_timeout(); break;
        }
    }
}

bool HeatTask::await(uint32_t timeout) {
    return osOK == m_mq.poll(m_state, timeout);
}

void HeatTask::do_work() {
    uint32_t time_count = 0;
    for (;;) {

        if (!sensor->is_steam_low()) {
            m_state = State::IDLE;
            break;
        }

        if (!sensor->is_steam_ok()) {
            m_state = State::TEMP_FAIL;
            break;
        }

        if (time_count >= config->heat_timeout) {
            m_state = State::TIMEOUT;
            break;
        }

        if ((sensor->steam_value() < config->steam_temp) &&
            (analog->kpa_value() < config->steam_kpa)) {
            
            parts->steam_heat_open();
            time_count += 1000;
        } else {
            parts->steam_heat_close();
            time_count = 0;
        }

        if (await(1000)) {
            break;
        }
    }
    parts->steam_heat_close();
}

void HeatTask::do_idle() {

    for (;;) {
        if (sensor->is_steam_low()) {
            m_state = State::WORK;
            break;
        }
        
        if (await(1000)) {
            break;
        }
    }
}

void HeatTask::do_fail() {
    await();
}

void HeatTask::do_timeout() {
    parts->valve_open(2);
    parts->steam_pump_open();
    if (!await(20 * 1000)) {
        m_state = State::IDLE;
    }
    parts->steam_pump_close();
    parts->valve_close(2);
}

}
